using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Collections;
using MSHelpLib.BaseCode;
using System.Windows.Forms;
using HtmlAgilityPack;


namespace MSHelpLib
{    
	/// <summary>
	/// Handles the processing of a URL, extracting the HTML file, parsing and patching html, extracting
	/// other files needed to display this page.
	/// </summary>
	public class HelpPageProcessing
	{
		private string		m_TempDir="";
		private string		m_URL="";		
	
		// Flags used to remove sections of the HTML code so that it works on PocketPC
		private bool		m_bRemoveScriptTags=true;
		private bool		m_bRemoveXMLTags=false;
        private bool        m_bRemoveDisplayNone = false;
		private bool        m_bRemoveSize = false;		
		private bool        m_bHTTPDecode = false;
        private bool        m_bIgnoreImages= false;

		private string		m_CurrentDir="";
		private string		m_helpFileDir="";
		private string		m_helpFileName="";
		private string		m_helpFileFullName="";
		private string		m_helpPageName="";
		private string		m_helpPrefix="";
		private string		m_Anchor="";
        private string      m_ArticalName = "";

        /// <summary>
        /// Name of Artical being viewed
        /// </summary>
        public string ArticalName
        {
            get { return m_ArticalName; }
            set { m_ArticalName = value; }
        }

		private IHelpSystem	m_HelpSystem=null;

		private static bool m_bFirst=true;
        
        /// <summary>
        /// Initializes a new instance of the <see cref="HelpPageProcessing"/> class.
        /// </summary>
        /// <param name="hs">The hs.</param>
        /// <param name="Url">The URL.</param>
        /// <param name="TempDir">The temp dir.</param>
        /// <param name="ArticalName">The name of the artical being processed, or empty string if not known</param>
		public HelpPageProcessing(IHelpSystem hs, string Url, string TempDir, string ArticalName)
		{			
			m_URL=Url;
            m_ArticalName = ArticalName;
			m_TempDir=TempDir;			
			m_HelpSystem=hs;

            SetFlags();

			if (m_bFirst)
			{
				m_bFirst=false;
				try
				{
					if (Directory.Exists(TempDir))
						Directory.Delete(TempDir);
				}
				catch
				{
				}
			}		
		}

        private void SetFlags()
        {
            if ((m_HelpSystem.Flags & (int)LoadFlags.RemoveXMLTags) != 0)
                m_bRemoveXMLTags = true;
            else
                m_bRemoveXMLTags = false;

            if ((m_HelpSystem.Flags & (int)LoadFlags.RemoveSizeNone) != 0)
                m_bRemoveSize = true;
            else
                m_bRemoveSize = false;

            if ((m_HelpSystem.Flags & (int)LoadFlags.RemoveScriptTags) != 0)
                m_bRemoveScriptTags = true;
            else
                m_bRemoveScriptTags = false;

            if ((m_HelpSystem.Flags & (int)LoadFlags.RemoveDisplayNone) != 0)
                m_bRemoveDisplayNone = true;
            else
                m_bRemoveDisplayNone = false;

            if ((m_HelpSystem.Flags & (int)LoadFlags.HTTPDecode) != 0)
                m_bHTTPDecode = true;
            else
                m_bHTTPDecode = false;

            if ((m_HelpSystem.Flags & (int)LoadFlags.IgnoreImages) != 0)
                m_bIgnoreImages = true;
            else
                m_bIgnoreImages = false;
        }

		/// <summary>
		/// Does the work
		/// </summary>
		/// <returns>Returns a string of the file to display</returns>
		public string Process()
		{
            SetFlags();

			if (!m_TempDir.EndsWith(@"\"))
				m_TempDir+=@"\";			
			
			if ((m_HelpSystem.Flags & (int)LoadFlags.WipeTempDir)!=0)
			{				
				m_HelpSystem.OnStatus(0,"Clearing old work files");
				try
				{
					Directory.Delete(m_TempDir,true);
				}
				catch
				{
				}
				try
				{
					Directory.CreateDirectory(m_TempDir);
				}
				catch
				{
				}
			}

			m_HelpSystem.OnStatus(0,"Processing URL");

			// Parse URL
			if (!GetURLParts(m_URL,ref m_helpFileFullName, ref m_helpPageName, ref m_Anchor))
				return "";
			
			m_CurrentDir=Path.GetDirectoryName(m_helpPageName);
			if (!m_CurrentDir.EndsWith(@"\"))
				m_CurrentDir+=@"\";

			string htmlFileName=m_TempDir+m_CurrentDir+"MSHelpPage.htm";
			htmlFileName=htmlFileName.Replace(@"/",@"\");
			htmlFileName=htmlFileName.Replace(@"\\",@"\");

			FileInfo fi2=new FileInfo(m_helpFileFullName);
			m_helpFileName=fi2.Name.ToLower();			
			IHelpFile LocalHelpFile=null;
			for(int i=0;i<m_HelpSystem.FilesLoaded;i++)
			{
				IHelpFile hf=m_HelpSystem.GetHelpFile(i);
				if (hf!=null)
				{
					if (hf.FInfo.Name.ToLower()==fi2.Name.ToLower())
					{
						LocalHelpFile=hf;
						break;						
					}
				}
			}

			if (LocalHelpFile==null)
			{
				IHelpFile Master=m_HelpSystem.GetHelpFile(0);				
				string NewFile=Master.FInfo.DirectoryName+@"\"+m_helpFileFullName;
				m_HelpSystem.Open(NewFile);
				LocalHelpFile=m_HelpSystem.GetHelpFile(m_HelpSystem.FilesLoaded-1);
			}

			m_helpFileDir=LocalHelpFile.FInfo.DirectoryName;
			if (!m_helpFileDir.EndsWith(@"\"))
				m_helpFileDir+=@"\";

			m_helpPrefix=LocalHelpFile.UrlPrefix;			

			// Find HelpPage file in Help File
			string helpPageText="";
			ArrayList FileList=null;

			m_HelpSystem.OnStatus(0,"Searching for content");
			IFileInfo helpPageInfo=m_HelpSystem.FindFile(m_helpPageName);			
			if (helpPageInfo==null)
			{
				helpPageText=@"<Html><H1>Error</H1><br>Failed to find file : "+m_helpPageName+@"</html>";
			}
            else if (helpPageInfo.Length<=0)
			{
				helpPageText=@"<Html><H1>Error</H1><br>Found file : "+m_helpPageName+@" but it has a length <=0</html>";				
			}

			// Extract helpPage as Text (Should always be HTML)			
			try
			{
				if (helpPageText=="")
				{
                    if (m_ArticalName=="")
					    m_HelpSystem.OnStatus(0,"Extracting Help Page");
                    else
                        m_HelpSystem.OnStatus(0, "Extracting '"+m_ArticalName+"'");

					helpPageText=m_HelpSystem.ExtractAsText(helpPageInfo);									
					if (helpPageText=="")
					{
						helpPageText="<H1>Error</H1><br>Failed to extract file from help file : "+helpPageInfo.FileName;
					}
					else
					{						
						if (m_bHTTPDecode)
						{							
                            if (m_ArticalName == "")
                                m_HelpSystem.OnStatus(0, "Decoding HTML Page");
                            else
                                m_HelpSystem.OnStatus(0, "Decoding '" + m_ArticalName+"'");
							helpPageText=HttpUtility.HtmlDecode(helpPageText);
						}
				
						// Parse helpPageText for files which need extracting (Images, css, etc..>) and patch up filenames
                        if (m_ArticalName=="")
						    m_HelpSystem.OnStatus(0,"Scanning HTML Page");
                        else
                            m_HelpSystem.OnStatus(0, string.Format("Scanning '{0}'",m_ArticalName));

						FileList=GetListOfFilesInHTMLPage(ref helpPageText);

						// Extract all extra files needed for this page.
						if ((FileList!=null) && (FileList.Count>0))
						{
                            if (m_ArticalName=="")
							    m_HelpSystem.OnStatus(0,"Extracting extra files required");
                            else
                                m_HelpSystem.OnStatus(0, "Extracting extra files required for '"+m_ArticalName+"'");
							ExtractFilesForURL(FileList, 0);
						}
					}
				}
			}
			catch(Exception ex)
			{
				helpPageText="<H1>Error</H1><br>An error has occured while processing page : "+helpPageInfo.FileName+"<br><br>Error Message:<br>"+ex.Message;
                if (FileList!=null)
				    FileList.Clear();   
			}

			try
			{
				m_HelpSystem.OnStatus(0,"Saving HTML Page");

				// Save patched helpPageText as file
				FileInfo fi=new FileInfo(htmlFileName);
				if (!Directory.Exists(fi.DirectoryName))
					Directory.CreateDirectory(fi.DirectoryName);

				StreamWriter sw=new StreamWriter(htmlFileName,false);
				sw.WriteLine(helpPageText);
				sw.Close();				
			}
			catch(Exception ex)
			{
				helpPageText="<H1>Error</H1><br>"+ex.Message;
                if (FileList!=null)
				    FileList.Clear();
			}

			// If we have Anchor, then add to the URL to pass to the WebBrowser Control.
			if (m_Anchor!="")
				htmlFileName+="#"+m_Anchor;

			// All Done
			return htmlFileName;
		}

        /// <summary>
        /// Gets the URL parts.
        /// </summary>
        /// <param name="Url">The URL.</param>
        /// <param name="HelpFileName">Name of the help file.</param>
        /// <param name="FileName">Name of the file.</param>
        /// <param name="Anchor">The anchor.</param>
        /// <returns></returns>
		public bool GetURLParts(string Url, ref string HelpFileName, ref string FileName, ref string Anchor)
		{            
			// Regex ParseURLRegEx= new Regex( @"ms-its:(?'HelpFile'.*)::(?'Topic'.*)", RegexOptions.IgnoreCase| RegexOptions.Singleline | RegexOptions.ExplicitCapture| RegexOptions.IgnorePatternWhitespace| RegexOptions.Compiled);
			// Regex ParseURLRegEx2= new Regex( @"ms-help:(?'HelpFile'.*)::(?'Topic'.*)", RegexOptions.IgnoreCase| RegexOptions.Singleline | RegexOptions.ExplicitCapture| RegexOptions.IgnorePatternWhitespace| RegexOptions.Compiled);

            HelpFileName="";
            FileName="";
            Anchor="";
			int idx=-1;
			int Type=0;
			if (Url.ToLower().StartsWith("ms-help:"))
				Type=8;
			if (Url.ToLower().StartsWith("ms-its:"))
				Type=7;

            if (Type == 0)
                Type = 0;

			string t=Url.Substring(Type);
			idx=t.IndexOf("::");
			if (idx!=-1)
			{
				HelpFileName=t.Substring(0,idx);
				t=t.Substring(idx+2);
			}
			idx=t.IndexOf("#");
			if (idx!=-1)
			{
				Anchor=t.Substring(idx);
				FileName=t.Substring(0,idx);
			}
			else
			{
				FileName=t;
			}

			if (FileName.ToLower().StartsWith("//hx/hxruntime/"))
			{					
				HelpFileName=@"hxruntime.hxs";
				FileInfo fi=new FileInfo(FileName);
				FileName=fi.Name;
			}

            if (HelpFileName == "")
            {
                HelpFileName = this.m_helpFileName;
                if (HelpFileName == "")
                    HelpFileName = m_HelpSystem.GetHelpFile(0).FileName;
            }

			HelpFileName=HelpFileName.Replace(@"\\",@"\");
			FileName=FileName.Replace(@"\\",@"\");

			return true;			
		}
		
		string ReplaceFileName(Match m)
		{
			string strReplace = m.ToString();

			// Process string.
			if (m.Groups["FileName"]==null)
				return strReplace;			

			string FileName=m.Groups["FileName"].Value;
			if (ProcessFind(FileName)=="")            
                return "";

			string HelpFileName="";
			string TopicName="";
			string Anchor="";
			GetURLParts(ProcessFind(FileName),ref HelpFileName,ref TopicName, ref Anchor);
			string NewName=m_TempDir+TopicName;
			
			NewName=NewName.Replace("/",@"\");
			NewName=NewName.Replace(@"\\",@"\");
			
			NewName="file://"+NewName;

			strReplace=strReplace.Replace(FileName,NewName);	
			return strReplace;
		}

		string ReplaceFileName2(Match m)
		{
			string strReplace = m.ToString();

			// Process string.
			if (m.Groups["FileName"]==null)
				return strReplace;			

			string FileName=m.Groups["FileName"].Value;
			if (FileName.ToLower().StartsWith("file:"))
				return strReplace;

			if (FileName.ToLower().StartsWith("http:"))
				return strReplace;

			if (FileName.ToLower().StartsWith("https:"))
				return strReplace;

			if (FileName.ToLower().StartsWith("mailto:"))
				return strReplace;

			if (FileName.StartsWith("#"))
			{
				// Leave alone.
				return strReplace;
			}

			string NewName=m_helpPrefix+m_helpFileFullName+"::"+m_CurrentDir+@"\"+FileName;

			strReplace=strReplace.Replace(FileName,NewName);	
			return strReplace;
		}

        private string CreateNewFileName(string FileName)
        {
            if (ProcessFind(FileName) == "")
                return "";

            string strReplace = FileName;
            string HelpFileName = "";
            string TopicName = "";
            string Anchor = "";
            GetURLParts(ProcessFind(FileName), ref HelpFileName, ref TopicName, ref Anchor);
            string NewName = m_TempDir + TopicName;

            NewName = NewName.Replace("/", @"\");
            NewName = NewName.Replace(@"\\", @"\");

            NewName = "file://" + NewName;

            strReplace = strReplace.Replace(FileName, NewName);
            return strReplace;
        }

		private string ProcessFind(string FileName)
		{
			string Trims="\n\r";

			FileName=FileName.Trim().Trim(Trims.ToCharArray());
            if (FileName == "")
                return "";

            if (FileName.ToLower().StartsWith("http://"))
                return "";

			// Make sure we are using the correct path.
			// In HTML files, file paths can be relative. The following line maps this revative
			// path to absolute in Help File.
			string HelpFileName="";
			string TopicName="";
			string Anchor="";

			PathMgr p=new PathMgr(m_CurrentDir);

			if (FileName.ToLower().StartsWith(m_helpPrefix))
			{				
				GetURLParts(FileName,ref HelpFileName, ref TopicName, ref Anchor);
				if (TopicName.StartsWith("/../"))
				{
					TopicName=TopicName.Substring(4);
					string []Parts=TopicName.Split('/');
					FileName=m_helpPrefix+Parts[0]+".HXS::";
					for(int i=1;i<Parts.GetLength(0);i++)
					{
						if (i>1)
							FileName+="/";
						FileName+=Parts[i];
					}
				}
				else if (HelpFileName.ToLower()==this.m_helpFileName)
				{
					p.CombinePath(TopicName);
					FileName=p.Path;
				}
				else
				{
					FileName=m_helpPrefix+HelpFileName+"::"+TopicName;
				}
			}
			else
			{
				p.CombinePath(FileName);
				FileName=p.Path;
			}
			

			if (!FileName.ToLower().StartsWith(m_helpPrefix))
				FileName=m_helpPrefix+FileName;
			GetURLParts(FileName,ref HelpFileName, ref TopicName, ref Anchor);
					
			if (HelpFileName.ToLower()==m_helpFileName)
			{
				if ((TopicName.StartsWith("..")) || (TopicName.StartsWith("/..")))
				{
					PathMgr pp=new PathMgr(m_CurrentDir);
					pp.CombinePath(TopicName);
					TopicName=pp.Path;
				}
				// TopicName=Path.GetFullPath(Path.Combine(this.m_CurrentDir,TopicName)).Substring(2);
			}			

			FileName=m_helpPrefix+m_helpFileDir+HelpFileName+"::"+TopicName;			

			return FileName;
		}

        /// <summary>
        /// Gets the list of files in HTML page.
        /// </summary>
        /// <param name="Text">The text.</param>
        /// <returns></returns>
		public ArrayList GetListOfFilesInHTMLPage(ref string Text)
		{
            ArrayList FilesList = new ArrayList();

            // Navigate html page via dom & find nodes with <Script <XML <Link <A <IMG tags
            // Create list of files which need to be exported & change filenames.
            // Remove <Script & <XML tags completly            
            HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
            doc.LoadHtml(Text);
            HtmlDocSearch SearchDoc = new HtmlDocSearch(doc);
            if (m_bRemoveXMLTags)
            {
                HtmlNodeCollection xmlNodeList = SearchDoc.SearchForTags("xml");
                foreach (HtmlNode node in xmlNodeList)
                {
                    if (node != null)
                        node.ParentNode.RemoveChild(node);                    
                }
            }

            if (m_bRemoveScriptTags)
            {
                HtmlNodeCollection scriptNodeList = SearchDoc.SearchForTags("script");
                foreach (HtmlNode node in scriptNodeList)
                {
                    if (node != null)
                        node.ParentNode.RemoveChild(node);
                }

                try
                {
                    string [] ScriptAttributeList= new string[] {
                        "OnSave", "OnClick","OnLoad","OnMouseOver","OnMouseIn","OnMouseOut",
                        "OnUnLoad","OnDblclick","OnMouseDOwn", "OnMouseUp","OnMouseMove",
                        "OnFocus","OnBlur","OnKeyPress","OnKeyDown","OnKeyUp","OnSubmit",
                        "OnReset","OnSelect","OnChange"};

                    foreach(string ScriptEvent in ScriptAttributeList)
                    {
                        HtmlAttributeCollection scriptAttributesList = SearchDoc.SearchForAttributes(ScriptEvent);
                        foreach (HtmlAttribute attribute in scriptAttributesList)
                        {
                            try
                            {
                                attribute.Value="";
                            }
                            catch (Exception ex)
                            {
                                Debug.WriteLine(ex.Message);
                            }
                        }
                    }                    
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
            }
            // <mshelp:link keywords="415c6855-91b2-4fb7-925d-38adbe715a6d" 

            HtmlNodeCollection msHelpList= SearchDoc.SearchForTags("mshelp:link");
            foreach (HtmlNode node in msHelpList)
            {
                node.Name = "a";
                string newname=node.Attributes["keywords"].Value;
                node.Attributes["keywords"].Name = "href";
                   node.Attributes["keywords"].Value = newname + ".htm";
            }

            if (m_bRemoveDisplayNone)
            {
                HtmlAttributeCollection xmlNodeList = SearchDoc.SearchForAttributes("style");
                foreach (HtmlAttribute attr in xmlNodeList)
                {
                    if (attr != null)
                    {
                        if (attr.Value.ToLower().IndexOf("display:none")!=-1)
                            attr.Value=attr.Value.ToLower().Replace("display:none", "");
                    }
                }
            }

            if (m_bRemoveSize)
            {                
            }

            if (m_bIgnoreImages == false)
            {
                HtmlAttributeCollection srcList = SearchDoc.SearchForAttributes("src");
                foreach (HtmlAttribute attribute in srcList)
                {
                    string FileName = ProcessFind(attribute.Value);

                    // Add file to list of files need to be extracted to display the current page
                    if (!FilesList.Contains(FileName))
                    {
                        // if (!FileName.ToUpper().EndsWith(".JS"))
                            FilesList.Add(FileName);
                    }

                    string NewFileName = CreateNewFileName(FileName);
                    attribute.Value = NewFileName;
                }
            }

            HtmlAttributeCollection hrefList = SearchDoc.SearchForAttributes("href");
            foreach (HtmlAttribute attribute in hrefList)
            {
                if (attribute.OwnerNode.Name.ToLower() != "link")
                    continue;

                string FileName = ProcessFind(attribute.Value);                

                // Add file to list of files need to be extracted to display the current page
                if (!FilesList.Contains(FileName))
                {
                    // if (!FileName.ToUpper().EndsWith(".JS"))
                        FilesList.Add(FileName);
                }

                string NewFileName = CreateNewFileName(FileName);
                attribute.Value = NewFileName;
            }

            // Create new htmlpage from dom with new changes.
            StringWriter sw = new StringWriter();
            doc.Save(sw);
            Text=sw.ToString();
            sw.Close();
            
            //// Parse HTML for CCS, ima, etc			
            //string regexContent=@"[\x2f a-zA-Z0-9\x5C\x2E\x28\x29\x23\x24\x25\x26\x27\x22\x21\x3F\x3E\x3D\x3C\x3B\x3A\x5B\x5D\x5E\x5F\x7D\x7C\x7B\x7E\x40\x2D\x2C\x2B\x2A]*\s*";
            //string regexFileName=@"\s*=\s*[""|'](?'FileName'[^""^']*)[""|']\s*";

            //Regex ScriptRegex = new Regex(@"<script[^>]*>.*</script>",
            //    RegexOptions.IgnoreCase
            //    | RegexOptions.Multiline
            //    | RegexOptions.Singleline
            //    | RegexOptions.IgnorePatternWhitespace
            //    | RegexOptions.Compiled);

            //Regex XMLRegex = new Regex(@"<\?xml.*\?>",
            //    RegexOptions.IgnoreCase
            //    | RegexOptions.Multiline
            //    | RegexOptions.Singleline
            //    | RegexOptions.IgnorePatternWhitespace
            //    | RegexOptions.Compiled);

            //Regex XMLRegex2 = new Regex(@"<xml[^>]*>.*</xml>",
            //    RegexOptions.IgnoreCase
            //    | RegexOptions.Multiline
            //    | RegexOptions.Singleline
            //    | RegexOptions.IgnorePatternWhitespace
            //    | RegexOptions.Compiled);

            //Regex SRCRegex = new Regex( 
            //    @"src"+regexFileName,
            //    RegexOptions.IgnoreCase
            //    | RegexOptions.Multiline
            //    | RegexOptions.Singleline
            //    | RegexOptions.IgnorePatternWhitespace
            //    | RegexOptions.Compiled);

            //Regex StyleSheetRegex = new Regex(				
            //    @"<link\s*"+regexContent+@"rel\s*=\s*[""|']stylesheet[""|']\s*"+regexContent + "href"+regexFileName,
            //    RegexOptions.IgnoreCase
            //    | RegexOptions.Multiline
            //    | RegexOptions.Singleline
            //    | RegexOptions.IgnorePatternWhitespace
            //    | RegexOptions.Compiled);

            //Regex HRefRegex = new Regex( 
            //    @"href"+regexFileName,
            //    RegexOptions.IgnoreCase
            //    | RegexOptions.Multiline
            //    | RegexOptions.Singleline
            //    | RegexOptions.IgnorePatternWhitespace
            //    | RegexOptions.Compiled);

            //Regex DisplayNoneRegEx = new Regex(
            //"display\\s*:\\s*(?<Type>\\S*)\\s*;",
            //RegexOptions.IgnoreCase
            //| RegexOptions.Multiline
            //| RegexOptions.Singleline
            //| RegexOptions.IgnorePatternWhitespace
            //| RegexOptions.Compiled);


            //Regex DisplayNoneRegEx2 = new Regex(
            //@"height\s*:\s*(?<Height>\S*\s*);",
            //RegexOptions.IgnoreCase
            //| RegexOptions.Multiline
            //| RegexOptions.Singleline
            //| RegexOptions.IgnorePatternWhitespace
            //| RegexOptions.Compiled);


            //Regex DisplayNoneRegEx3 = new Regex(
            //@"width\s*:\s*(?<Width>\S*\s*);",
            //RegexOptions.IgnoreCase
            //| RegexOptions.Multiline
            //| RegexOptions.Singleline
            //| RegexOptions.IgnorePatternWhitespace
            //| RegexOptions.Compiled);
			
            //if (m_bRemoveDisplayNone)
            //    Text = DisplayNoneRegEx.Replace(Text, "");                

            //if (m_bRemoveSize)
            //{
            //    Text = DisplayNoneRegEx2.Replace(Text, "");			
            //    Text = DisplayNoneRegEx3.Replace(Text, "");
            //}
			
            //StringBuilder s=new StringBuilder(Text);			
            //if (StyleSheetRegex.IsMatch(Text))
            //{				
            //    Match m = StyleSheetRegex.Match(Text);
            //    while (m.Success)
            //    {										
            //        string FileName=ProcessFind(m.Groups["FileName"].ToString());

            //        // Add file to list of files need to be extracted to display the current page
            //        if (!FilesList.Contains(FileName))
            //            FilesList.Add(FileName);

            //        m=m.NextMatch();
            //    }
            //    Text=StyleSheetRegex.Replace(Text,new MatchEvaluator(ReplaceFileName));
            //}

            //if (SRCRegex.IsMatch(Text))
            //{								
            //    Match m = SRCRegex.Match(Text);
            //    while (m.Success)
            //    {					
            //        string FileName=ProcessFind(m.Groups["FileName"].ToString());

            //        // Add file to list of files need to be extracted to display the current page
            //        if (FileName != "")
            //        {
            //            FileName=FileName.ToLower();
            //            bool bAddFile = true;
            //            if (this.m_bIgnoreImages)
            //            {
            //                string FileExt=Path.GetExtension(FileName);
            //                switch (FileExt)
            //                {
            //                    case ".bmp":
            //                    case ".gif":
            //                    case ".png":
            //                    case ".tif":
            //                    case ".tiff":
            //                    case ".jpg":
            //                        bAddFile = false;
            //                        break;

            //                    default:
            //                        bAddFile = true;
            //                        break;
            //                }
            //            }

            //            // Add file to list of files to extract
            //            if ((bAddFile) && (FilesList.Contains(FileName)==false))
            //                FilesList.Add(FileName);
            //        }

            //        m=m.NextMatch();
            //    }
            //    Text=SRCRegex.Replace(Text,new MatchEvaluator(ReplaceFileName));
            //}

            //if (HRefRegex.IsMatch(Text))
            //{
            //    Text=HRefRegex.Replace(Text,new MatchEvaluator(ReplaceFileName2));
            //}
			            
			return FilesList;
		}

        /// <summary>
        /// Files the loaded.
        /// </summary>
        /// <param name="FileName">Name of the file.</param>
        /// <returns></returns>
		public bool FileLoaded(string FileName)
		{
			FileInfo fi=new FileInfo(FileName);
			for(int i=0;i<m_HelpSystem.FilesLoaded;i++)			
			{
				IHelpFile helpFile=m_HelpSystem.GetHelpFile(i);
				FileInfo fi2=new FileInfo(helpFile.FileName);
				if(fi2.FullName.ToLower()==fi.FullName.ToLower())
					return true;
				fi2=null;
			}
			return false;
		}

        /// <summary>
        /// Extracts the files for URL.
        /// </summary>
        /// <param name="FileList">The file list.</param>
        /// <param name="Level">The level.</param>
		public void ExtractFilesForURL(ArrayList FileList, int Level)
		{
			// Get FilesList & Extract Files to Temp Dir
			IHelpFile hf=(IHelpFile)m_HelpSystem.GetHelpFile(0);

			if ((FileList!=null) && (FileList.Count>0))
			{
                int cnt = 1;
                int max = FileList.Count;
				foreach(object obj in FileList)
				{
                    m_HelpSystem.OnStatus(2, string.Format("Extracting File {0} of {1}",cnt,max));
                    m_HelpSystem.OnProgress(cnt++, max);

					string FileName=(string)obj;                    

					string HelpFileName="";
					string TopicName="";					
					string Anchor="";

					if (!FileName.ToLower().StartsWith(hf.UrlPrefix))
						FileName=hf.UrlPrefix+FileName;

					if (GetURLParts(FileName,ref HelpFileName, ref TopicName, ref Anchor))
					{	
						// if help file (which contains file required for current page) is not loaded, then load it.
						if (!this.FileLoaded(HelpFileName))
						{
							try
							{
								m_HelpSystem.Open(HelpFileName);
							}
							catch
							{
							}
						}
					}

                    // Some files are HTTP:// and include parameters in the URL, so remove them.
                    int idx = TopicName.IndexOf("?");
                    if (idx != -1)
                    TopicName = TopicName.Substring(0, idx);                    

					// Check to see if file already exists.										
					FileInfo Fi=new FileInfo(TopicName.Replace(@"\","/"));
					string path=m_TempDir+Fi.FullName;
					path=path.Replace("/",@"\");
					path=path.Replace(@"\\",@"\");
					if (File.Exists(path))
						continue;

					if (((TopicName.ToLower().EndsWith(".htm")) || (TopicName.ToLower().EndsWith(".html"))) && (Level<2))
					{
                        string HTMLText2 = "";
                        IFileInfo fileInfo = null;
                        fileInfo=m_HelpSystem.FindFile(TopicName);
                        if (fileInfo != null)
                        {
                            HTMLText2 = m_HelpSystem.ExtractAsText(fileInfo);

                            if (!HTMLText2.StartsWith("##-"))
                            {
                                ArrayList subFilesList = GetListOfFilesInHTMLPage(ref HTMLText2);
                                ExtractFilesForURL(subFilesList, Level + 1);
                            }
                            else
                            {
                                HTMLText2 = HTMLText2.Substring(3);
                            }
                            if (File.Exists(path))
                                File.Delete(path);

                            StreamWriter st = new StreamWriter(path);
                            st.WriteLine(HTMLText2);
                            st.Close();
                        }
					}
//					else if (TopicName.ToLower().EndsWith(".js"))
//					{
//						// Load JScript File.
//						IFileInfo JSFileInfo=m_HelpSystem.FindFile(TopicName);
//						if (JSFileInfo!=null)
//						{							
//							string JScriptText=m_HelpSystem.ExtractAsText(JSFileInfo);
//							FileInfo Fi=new FileInfo(TopicName);
//							string path=m_TempDir+Fi.Name;
//
//							StreamWriter st=new StreamWriter(path);
//							st.WriteLine(JScriptText);
//							st.Close();
//
//							// Parse JScript Text for images to load.							
//							string [] extraFiles = { @"(?'FileName'\w*\.css)"
//													   ,@"(?'FileName'\w*\.gif)"
//													   ,@"(?'FileName'\w*\.js)"
//													   ,"[\"|\'|\\\\|:|/](?\'FileName\'.*.css)[\"|\']"
//													   ,"[\"|\'|\\\\|:|/](?\'FileName\'.*.gif)[\"|\']"
//													   ,"[\"|\'|\\\\|:|/](?\'FileName\'.*.js)[\"|\']"
//												   };
//
//							foreach(string regExpression in extraFiles)
//							{
//								Regex extraFilesRegEx = new Regex(regExpression, RegexOptions.IgnorePatternWhitespace | RegexOptions.IgnoreCase);							
//								if (extraFilesRegEx.IsMatch(JScriptText))
//								{				
//									Match m = extraFilesRegEx.Match(JScriptText);
//									while (m.Success)
//									{										
//										string extraFileName=m.Groups["FileName"].ToString();
//										ExtractFile(extraFileName,true);
//										m=m.NextMatch();
//									}
//								}
//							}
//						}
//					}
					else
					{
						ExtractFile(TopicName,true);
					}				
				}
			}
		}

		private bool ExtractFile(string TopicName, bool bMakeDirectory)
		{
			try
			{
				// Extract all other files as is						
				string FileName2=TopicName;
				FileName2=FileName2.Replace(@"\","/");
				FileInfo newFI=new FileInfo(FileName2);				
				string path="";
				if (bMakeDirectory)
				{
					path=m_TempDir+ Path.GetDirectoryName(TopicName)+@"\"+newFI.Name; // FileName2
					Directory.CreateDirectory(Path.GetDirectoryName(path));
				}
				else
					path=m_TempDir+newFI.Name; // FileName2

				// Only extract file if it does not exist.
				if (File.Exists(path))
					return true;

				// Make sure the file exists in the Help Files				
				IFileInfo extractFileInfo=m_HelpSystem.FindFile(FileName2);
				if (extractFileInfo==null)
					return false;
							
				// Extract the file
				try
				{                    
					m_HelpSystem.OnStatus(1,"Extracting '"+extractFileInfo.FileName+"'");

					// Extract file
					System.IO.FileStream st=new FileStream(path,FileMode.CreateNew);

					MemoryStream ms=m_HelpSystem.Extract(extractFileInfo);
					if (ms!=null)
						st.Write(ms.ToArray(),0,(int)ms.Length);
					st.Close();

					m_HelpSystem.OnStatus(1,"");

					return true;
				}
				catch(Exception ex)
				{
					Debug.WriteLine(ex.Message);
					return false;
				}
			}
			catch(Exception ex)
			{
				Debug.WriteLine(ex.Message);
				return false;
			}
		}
    }
}
